package ext.generic.part;


import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.PropertyResourceBundle;
import java.util.Vector;

import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import wt.doc.WTDocument;
import wt.epm.EPMDocument;
import wt.epm.EPMDocumentMaster;
import wt.epm.structure.EPMReferenceLink;
import wt.epm.structure.EPMStructureHelper;
import wt.fc.ObjectReference;
import wt.fc.Persistable;
import wt.fc.PersistenceHelper;
import wt.fc.QueryResult;
import wt.fc.ReferenceFactory;
import wt.fc.WTObject;
import wt.fc.collections.WTArrayList;
import wt.httpgw.URLFactory;
import wt.iba.value.IBAHolder;
import wt.inf.container.WTContainer;
import wt.lifecycle.LifeCycleManaged;
import wt.method.RemoteAccess;
import wt.org.WTPrincipal;
import wt.org.WTPrincipalReference;
import wt.org.WTUser;
import wt.part.PartType;
import wt.part.WTPart;
import wt.part.WTPartHelper;
import wt.part.WTPartMaster;
import wt.part.WTPartStandardConfigSpec;
import wt.project.Role;
import wt.query.QuerySpec;
import wt.query.SearchCondition;
import wt.session.SessionHelper;
import wt.session.SessionServerHelper;
import wt.util.WTContext;
import wt.util.WTException;
import wt.util.WTMessage;
import wt.util.WTProperties;
import wt.vc.Iterated;
import wt.vc.VersionControlHelper;
import wt.vc.views.ViewHelper;
import wt.vc.wip.WorkInProgressHelper;
import wt.vc.wip.Workable;
import wt.workflow.engine.ProcessData;
import wt.workflow.engine.WfActivity;
import wt.workflow.engine.WfProcess;
import wt.workflow.work.WfAssignedActivity;
import wt.workflow.work.WorkItem;

import com.ptc.netmarkets.util.beans.NmCommandBean;
import com.ptc.netmarkets.util.misc.NmActionServiceHelper;
import com.ptc.windchill.enterprise.part.commands.PartDocServiceCommand;

import ext.com.core.CoreUtil;
import ext.com.iba.IBAUtil;
import ext.com.workflow.WorkflowUtil;
import ext.generic.wfaugment.processors.WfAugmentUtil;

/**
 * 零部件签审流程所使用的常用方法类
 */
public class PartWorkflowUtil implements RemoteAccess, Serializable
{
    private static String RESOURCE = "ext.generic.part.partResource";
    private static String PROPERTIES = "ext.generic.part.generic_part";
    // ext/generic/part/generic_part.properties
    private static String CLASSNAME = PartWorkflowUtil.class.getName();
    private static boolean VERBOSE = false;
    private static Locale locale = null;
    private static String path = "";
    private static String doc_review_guide_sheet_name = "doc";
    public static String PROCESS_INFO_CLEAR_LABEL = "";
    public static Hashtable reviewDocTypes = new Hashtable();
    // key= container oid; value=hashtable of review doc types
    public static String SYSTEM_DESIGN_VIEW_NAME = "ProjectDesign";
    // 根据用户环境进行调整
    //workflowParticipant.properties文件路径
    private static String filePath= "ext.generic.workflow.workflowParticipant";
    static
    {
        try
        {
            VERBOSE = (WTProperties.getLocalProperties()).getProperty("ext.generic.part.verbose", false);
            locale = SessionHelper.manager.getLocale();
            path = WTContext.getContext().getCodeBase().toString();
        }
        catch (Throwable throwable)
        {
            throw new ExceptionInInitializerError(throwable);
        }
    }

    public PartWorkflowUtil()
    {
    }

    /**
     * 读取指定Sheet中指定活动名称的签审信息，同时构造出签审环节 用于WTDocument
     */
    public static Hashtable getReviewDocTypes(WTContainer container) throws IOException, WTException
    {
        if (VERBOSE)
            System.out.println(">>>" + CLASSNAME + ".getReviewDocTypes()");
        Hashtable reviewDocTypes1 = new Hashtable();
        // 如果当前缓存中已经存在随签文档类型信息,则不要再检查review guide

        if (reviewDocTypes.get(container.toString()) != null)
        {
            return (Hashtable) reviewDocTypes.get(container.toString());
        }

        // 获取review guide文件路径
        String wfConfigFilePath = ext.generic.wfaugment.processors.WfAugmentUtil.getConfigFilePath(container, WTDocument.class);
        if (VERBOSE)
            System.out.println("	签审指南路径=" + wfConfigFilePath);
        if (wfConfigFilePath == null || wfConfigFilePath.length() == 0)
            return reviewDocTypes1;

        // 加载review guide文件
        XSSFWorkbook wb = new XSSFWorkbook(new FileInputStream(wfConfigFilePath));
        if (wb == null)
            return null;
        XSSFSheet sheet = wb.getSheet(doc_review_guide_sheet_name);
        if (sheet == null)
        {
            if (VERBOSE)
                System.out.println("	没有获取到名称为'" + doc_review_guide_sheet_name + "' sheet.");
            return null;
        }

        // 根据文档大类和小类信息解析review guide文件内容
        Iterator rows = sheet.rowIterator();
        String cellValue = "";
        XSSFRow row;
        XSSFCell cell;

        String langMark;
        int columnMark;

        int bigTypeCol = 0;
        int detailTypeCol = 1;
        int reviewFlagCol = 2;

        row = (XSSFRow) rows.next(); //第一行
        String bigType = "";
        int rowNumber = 1;
        while (rows.hasNext())
        {
            String detailType = "";
            String reviewFlag = "";
            row = (XSSFRow) rows.next();
            cell = row.getCell((short) bigTypeCol);
            System.out.println("cell="+cell);            
            if (cell != null)
            {
                cellValue = cell.getStringCellValue().trim();
                if (cellValue != null && cellValue.length() > 0)
                {
                    bigType = cellValue;
                    rowNumber++;
                   // continue;
                }
            }
            if (VERBOSE)
                System.out.println("    big type=" + bigType);
            if (bigType != null && bigType.length() > 0)
            {
                cell = row.getCell((short) detailTypeCol);
                System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>detailTypeCol="+cell);
                if (cell != null)
                {
                    detailType = "";
                    reviewFlag = "";
                    cellValue = cell.getStringCellValue().trim();
                    detailType = cellValue;
                    cell = row.getCell((short) reviewFlagCol);
                    System.out.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxreviewFlagCol="+reviewFlagCol);
                    if (cell != null)
                    {
                        cellValue = cell.getStringCellValue().trim();
                        reviewFlag = cellValue;
                        if (reviewFlag.startsWith("Y"))
                        {
                            reviewFlag = "Y";
                        }
                        else
                        {
                            reviewFlag = "N";
                        }
                    }
                    else
                    {
                        reviewFlag = "N";
                    }
                    System.out.println("***********************************"+bigType + "." + detailType);
                    reviewDocTypes1.put(bigType + "." + detailType, reviewFlag);
                }
            }
            rowNumber++;
        }
        if (VERBOSE)
            System.out.println("	row number=" + rowNumber);
        reviewDocTypes.put(container.toString(), reviewDocTypes1);

        if (VERBOSE)
        {
            System.out.println("	reviewDocTypes1=" + reviewDocTypes1);
            System.out.println("<<<" + CLASSNAME + ".getReviewDocTypes()");
        }
        return reviewDocTypes1;

    }

    /**
     * 检查流程的角色参与者
     */
    public static void checkWorkflowParticipantsRoles(Object processObj, Vector roleV) throws WTException
    {
        if ((processObj == null) || (roleV == null) || (roleV.size() <= 0))
            return;
        WfProcess wfprocess = null;
        try
        {
            wfprocess = WorkflowUtil.getProcess(processObj);
            if (wfprocess == null)
            {
                String errorInfo = WTMessage.getLocalizedMessage(RESOURCE, "1", null, locale);
                throw new WTException(errorInfo);
            }

        }
        catch (WTException e)
        {
            e.printStackTrace();
            Object params[] =
            { e.getLocalizedMessage() };
            String errorInfo = WTMessage.getLocalizedMessage(RESOURCE, "2", params, locale.CHINA);
            throw new WTException(errorInfo);
        }
        checkRoles(wfprocess, roleV);
    }

    /**
     * 检查角色的参与者是否具备
     */
    public static void checkRoles(WfProcess wfprocess, Vector roleV) throws WTException
    {
        if (wfprocess == null || roleV == null || roleV.size() == 0)
            return;

        String badRoles = "";

        try
        {
            wt.team.Team team = (wt.team.Team) ((wt.team.TeamReference) ((wt.team.TeamManaged) wfprocess).getTeamId()).getObject();
            for (int i = 0; i < roleV.size(); i++)
            {
                Role role = Role.toRole((String) roleV.elementAt(i));
                Enumeration enums = team.getPrincipalTarget(role);

                boolean bCheckRoleOK = false;

                while (enums != null && enums.hasMoreElements())
                {
                    WTPrincipalReference principalRef = (WTPrincipalReference) enums.nextElement();
                    if (principalRef == null || principalRef.isDisabled())
                        continue;
                    bCheckRoleOK = true;
                    break;
                }

                if (!bCheckRoleOK)
                {
                	//弹出角色没有选择用户
                    if (badRoles.length() == 0)
                        //badRoles = role.getDisplay();
                    	badRoles = role.getLocalizedMessage( SessionHelper.getLocale() );
                    else
                        //badRoles += "," + role.getDisplay();
                    	badRoles += "," +role.getLocalizedMessage( SessionHelper.getLocale() );
                    continue;
                }
            }
        }
        catch (WTException e)
        {
            e.printStackTrace();
            Object params[] =
            { e.getLocalizedMessage() };
            String errorInfo = WTMessage.getLocalizedMessage(RESOURCE, "2", params, locale.CHINA);
            throw new WTException(errorInfo);
        }

        if (badRoles.length() > 0)
        {
            Object params[] =
            { badRoles };
            String errorInfo = WTMessage.getLocalizedMessage(RESOURCE, "3", params, locale.CHINA);
            throw new WTException(errorInfo);
        }
    }

    /**
     * 从零部件流程中获取随签对象列表；该方法供零部件流程中“编制”和“修改”任务页面（JSP）调用
     * @param workItemOid
     * @return
     * @throws WTException
     */
    public static WTArrayList getReviewObjs(String workItemOid)
    {
    	boolean flag = SessionServerHelper.manager.setAccessEnforced(false);
    	
    	WTArrayList reviewObjList = new WTArrayList();
    	
    	try{
    		 if (VERBOSE)
    	            System.out.println(">>>" + CLASSNAME + ".getReviewObjs()");        
    	       
    	        
    	        Persistable obj = CoreUtil.getWTObjectByOid(workItemOid);
    	        
    	        WorkItem workItem = (WorkItem) obj;       
    	        WfAssignedActivity wfAssignedActivity = (WfAssignedActivity) workItem.getSource().getObject();
    	        WTArrayList reviewObjs = (WTArrayList) (wfAssignedActivity.getContext().getValue("reviewObjs"));
    	        
    	        //遍历流程中的reviewObjs，处理被删除的零部件，文档暂不处理
    	        if(reviewObjs !=null){
    	        	for (int i = 0; i < reviewObjs.size(); i++) {
    					Object objt = reviewObjs.get(i);
    					
    					if(objt != null && objt instanceof ObjectReference){
    						ObjectReference ref = (ObjectReference) objt;
    						objt = ref.getObject();
    					}
    					if(objt != null && objt instanceof WTPart){
    						WTPart part = (WTPart) objt;
    						
    						part = CoreUtil.getWTPartByNumberAndView(part.getNumber(), part.getViewName());
    						
    						if( part != null ){
    							reviewObjList.add(part);
    						}					
    					}else if(objt != null){
    						//对于其他类型暂时不处理
    						reviewObjList.add(objt);
    						
    					}
    					
    				}
    	        }       
    	        if (VERBOSE)
    	        {
    	            //System.out.println("	getReviewObjs in JSP reviewObjs.size():" + reviewObjs.size());
    	            System.out.println("<<<" + CLASSNAME + ".getReviewObjs()");
    	        }
    		
    	} catch (WTException e) {
			e.printStackTrace();
		}finally{
    		SessionServerHelper.manager.setAccessEnforced( flag );
    	}
    	
    	

       
           
        return reviewObjList;
    }

    /**
     *根据流程任务获取随签对象(附带流程主对象)
     * @param workItemOid
     * @return
     * @throws WTException
     */
    public static Vector getReviewObjsWithTopPart(String workItemOid) throws WTException
    {
//        Vector reviewObjs = new Vector();   	
    	List reviewObjs = new ArrayList();
        Vector optionalReviewObjs = new Vector();
        Vector returnVector = new Vector();
        Persistable obj = CoreUtil.getWTObjectByOid(workItemOid);
        WorkItem workItem = (WorkItem) obj;
        WfAssignedActivity wfAssignedActivity = (WfAssignedActivity) workItem.getSource().getObject();
        reviewObjs = (List) (wfAssignedActivity.getContext().getValue("reviewObjs"));
        WTPart pbo = (WTPart) (wfAssignedActivity.getContext().getValue("primaryBusinessObject"));
        optionalReviewObjs = getReviewObjects(pbo, true);
        for (int i = 0; i < optionalReviewObjs.size(); i++)
        {
            Persistable persistable = (Persistable) optionalReviewObjs.elementAt(i);
            if (!reviewObjs.contains(persistable))
                returnVector.add(persistable);
        }
        return returnVector;
    }

    /**
     * 【流程直接调用】初始化随签对象列表；该程序供零部件流程启动时调用
     * @param pbo
     * @return
     * @throws WTException
     */
    public static WTArrayList initializeReviewObjects(WTObject pbo) throws WTException
    {
        WTPart primaryPart = (WTPart) pbo;
        if (isSystemDesignBom(primaryPart))
        {
            // 工程项目材料清单
            return new WTArrayList(getSystemReviewObjects(primaryPart, true));
        }
        else
        {
            return new WTArrayList(getReviewObjects(primaryPart, true));
        }
    }

    /**
     * 判断零部件是否为系统设计的材料清单
     * @param part
     * @return
     */
    public static boolean isSystemDesignBom(WTPart part)
    {
        boolean retrunValue = false;
        PartType AsmType = part.getPartType();
        if (VERBOSE)
        {
            System.out.println("!!!!!AsmType = " + AsmType.getDisplay() + "StringValue = " + AsmType.getStringValue());
        }
        if (AsmType.getStringValue().equalsIgnoreCase("wt.part.PartType.projectMaterialList"))
        {
            retrunValue = true;
        }
        if (VERBOSE)
        {
            System.out.println("!!!!!retrunValue = " + retrunValue);
        }
        return retrunValue;
    }

    /**
     * 获取零部件流程随签对象列表
     *
     * @param myPrimaryPart 当前零部件，一般是零部件流程的PBO
     * @param recurse 是否递归处理产品结构
     */
    public static Vector getReviewObjects(WTPart myPrimaryPart, boolean recurse) throws WTException
    {
        Hashtable objectCache = new Hashtable(); // key= review object oid,
        // value=review object
        boolean includeDoc = true;
        getReviewObjects(myPrimaryPart, myPrimaryPart, recurse, includeDoc, objectCache);
        if (VERBOSE)
        {
            System.out.println("	object cache count=" + objectCache.size());
            System.out.println("	object cache=" + objectCache);
        }

        return new Vector(objectCache.values());
    }
    
    
   

    /**
     * 针对某个零部件获取流程随签对象列表
     *
     * @param thePart
     *            当前零部件
     * @param recurse
     *            是否递归处理产品结构
     * @param incluedeDoc
     *            是否包括相关文档和CAD文档
     * @param objectCache
     *            随签对象缓存表：key= oid of object master; value= the object
     */
    private static void getReviewObjects(WTPart thePart, WTPart pbo, boolean recurse, boolean includeDoc, Hashtable objectCache) throws WTException
    {
        if (VERBOSE)
        {
            System.out.println(">>>" + CLASSNAME + ".getReviewObjects()---遍历 " + thePart.getDisplayIdentity());
        }
        if (thePart == pbo)
        {
            objectCache.put(thePart.getMaster().toString(), thePart);
            if (VERBOSE)
            {
                System.out.println("	添加 " + thePart.getDisplayIdentity() + " 到签审表");
            }
            if (includeDoc)
            {
                getReviewDocuments(thePart, pbo, objectCache);
                getReviewCADDocuments(thePart, pbo, objectCache);
            }
            if (recurse)
            {
                // 根据视图找子件
                QueryResult subNodes = WTPartHelper.service.getUsesWTParts(thePart, WTPartStandardConfigSpec.newWTPartStandardConfigSpec(ViewHelper.service.getView(pbo.getViewName()), null));
                while (subNodes.hasMoreElements())
                {
                    Persistable aSubNodePair[] = (Persistable[]) subNodes.nextElement();
                    if (aSubNodePair[1] instanceof WTPart)
                    {
                        WTPart tempPart = (WTPart) aSubNodePair[1];
                        getReviewObjects(tempPart, pbo, recurse, includeDoc, objectCache);
                    }
                    else if (aSubNodePair[1] instanceof WTPartMaster)
                    {
                        WTPartMaster wtpartmaster = (WTPartMaster) aSubNodePair[1];
                        if (VERBOSE)
                        {
                            System.out.println("	零部件 " + wtpartmaster.getIdentity() + " 没有合适的版本不进行处理");
                        }
                    }
                }
            }
        }
        else
        {
            if (objectCache.get(thePart.getMaster().toString()) != null)
                return;
            //modified by Harry Cao on 2012-03-15://比对更新者
            WTPrincipal pboCreator = pbo.getModifier().getPrincipal();
            WTPrincipal thePartCreator = thePart.getModifier().getPrincipal();

            String currentPartState = thePart.getLifeCycleState().toString();
            boolean stillDoRecurse = false;
            if (currentPartState.equals("INWORK"))
            {
                if (pboCreator.getName().equals(thePartCreator.getName())) //比对更新者
                {
                    objectCache.put(thePart.getMaster().toString(), thePart);
                    if (VERBOSE)
                    {
                        System.out.println("	添加 " + thePart.getDisplayIdentity() + "’到签审表");
                    }
                    if (includeDoc)
                    {
                        getReviewDocuments(thePart, pbo, objectCache);
                        getReviewCADDocuments(thePart, pbo, objectCache);
                    }
                    stillDoRecurse = true;
                }
            }
            else if (currentPartState.equals("WAITREVIEW"))
            {
                objectCache.put(thePart.getMaster().toString(), thePart);
                if (VERBOSE)
                {
                    System.out.println("	添加 " + thePart.getDisplayIdentity() + "’到签审表");
                }
                if (includeDoc)
                {
                    getReviewDocuments(thePart, pbo, objectCache);
                    getReviewCADDocuments(thePart, pbo, objectCache);
                }
                stillDoRecurse = true;
            }
            //modified by harry cao on 20120315:无论如何情况，都继续递归；主要是为制造BOM流程
            else if (currentPartState.equals("RELEASED"))
            {
                stillDoRecurse = true;
            }
            if (recurse && stillDoRecurse)
            {
                // 根据视图找子件
                QueryResult subNodes = WTPartHelper.service.getUsesWTParts(thePart, WTPartStandardConfigSpec.newWTPartStandardConfigSpec(ViewHelper.service.getView(pbo.getViewName()), null));
                while (subNodes.hasMoreElements())
                {
                    Persistable aSubNodePair[] = (Persistable[]) subNodes.nextElement();
                    if (aSubNodePair[1] instanceof WTPart)
                    {
                        WTPart tempPart = (WTPart) aSubNodePair[1];
                        getReviewObjects(tempPart, pbo, recurse, includeDoc, objectCache);
                    }
                    else if (aSubNodePair[1] instanceof WTPartMaster)
                    {
                        WTPartMaster wtpartmaster = (WTPartMaster) aSubNodePair[1];
                        if (VERBOSE)
                        {
                            System.out.println("	零部件 " + wtpartmaster.getIdentity() + " 没有合适的版本不进行处理");
                        }
                    }
                }
            }
        }
        if (VERBOSE)
            System.out.println("<<<" + CLASSNAME + ".getReviewObjects()---遍历结束 " + thePart.getDisplayIdentity());
    }

    /**
     * 系统设计随签对象获取
     *
     * @param myPrimaryPart
     * @param recurse
     * @return
     * @throws WTException
     */
    public static Vector getSystemReviewObjects(WTPart myPrimaryPart, boolean recurse) throws WTException
    {
        Hashtable objectCache = new Hashtable(); // key= review object oid,
        // value=review object
        if (VERBOSE)
        {
            System.out.println(">>>>>>>>>>>>" + CLASSNAME + ".getSystemReviewObjects()");
        }
        getSystemReviewObjects(myPrimaryPart, myPrimaryPart, recurse, objectCache);
        if (VERBOSE)
        {
            System.out.println("	object cache count=" + objectCache.size());
            System.out.println("	object cache=" + objectCache);
            System.out.println("<<<<<<<<<<<" + CLASSNAME + ".getSystemReviewObjects()");
        }
        return new Vector(objectCache.values());
    }

    /**
     * 针对某个零部件获取【系统设计】零部件流程随签对象列表
     *
     * @param thePart
     *            当前零部件
     * @param pbo
     *
     * @param recurse
     *            是否递归处理产品结构
     * @param objectCache
     *            随签对象缓存表：key= oid of object master; value= the object
     */
    private static void getSystemReviewObjects(WTPart thePart, WTPart pbo, boolean recurse, Hashtable objectCache) throws WTException
    {
        if (VERBOSE)
        {
            System.out.println(">>>" + CLASSNAME + ".getSystemReviewObjects()---遍历 " + thePart.getDisplayIdentity());
        }
        if (thePart == pbo)
        {
            objectCache.put(thePart.getMaster().toString(), thePart);
            if (VERBOSE)
            {
                System.out.println("	添加 " + thePart.getDisplayIdentity() + " 到签审表");
            }

            if (recurse)
            {
                // 根据视图找子件
                QueryResult subNodes = WTPartHelper.service.getUsesWTParts(thePart, WTPartStandardConfigSpec.newWTPartStandardConfigSpec(ViewHelper.service.getView(SYSTEM_DESIGN_VIEW_NAME), null));
                while (subNodes.hasMoreElements())
                {
                    Persistable aSubNodePair[] = (Persistable[]) subNodes.nextElement();
                    if (aSubNodePair[1] instanceof WTPart)
                    {
                        WTPart tempPart = (WTPart) aSubNodePair[1];
                        getSystemReviewObjects(tempPart, pbo, recurse, objectCache);
                    }
                    else if (aSubNodePair[1] instanceof WTPartMaster)
                    {
                        WTPartMaster wtpartmaster = (WTPartMaster) aSubNodePair[1];
                        if (VERBOSE)
                        {
                            System.out.println("	零部件 " + wtpartmaster.getIdentity() + " 没有合适的版本不进行处理");
                        }
                    }
                }
            }
        }
        else
        {
            if (objectCache.get(thePart.getMaster().toString()) != null)
                return;
            WTPrincipal pboCreator = pbo.getModifier().getPrincipal();
            WTPrincipal thePartCreator = thePart.getModifier().getPrincipal();
            String currentPartState = thePart.getLifeCycleState().toString();
            boolean stillDoRecurse = true; //遍历所有层
            if (thePart.isEndItem())
            { //当为成品的时候，才添加到随签对象列表
                if (currentPartState.equals("INWORK"))
                {
                    if (pboCreator.getName().equals(thePartCreator.getName()))
                    {
                        objectCache.put(thePart.getMaster().toString(), thePart);
                        if (VERBOSE)
                        {
                            System.out.println("	添加 " + thePart.getDisplayIdentity() + "’到签审表");
                        }
                    }
                }
                else if (currentPartState.equals("WAITREVIEW"))
                {
                    objectCache.put(thePart.getMaster().toString(), thePart);
                    if (VERBOSE)
                    {
                        System.out.println("	添加 " + thePart.getDisplayIdentity() + "’到签审表");
                    }
                }
            }

            if (recurse && stillDoRecurse)
            {
                // 根据视图找子件
                QueryResult subNodes = WTPartHelper.service.getUsesWTParts(thePart, WTPartStandardConfigSpec.newWTPartStandardConfigSpec(ViewHelper.service.getView(SYSTEM_DESIGN_VIEW_NAME), null));
                while (subNodes.hasMoreElements())
                {
                    Persistable aSubNodePair[] = (Persistable[]) subNodes.nextElement();
                    if (aSubNodePair[1] instanceof WTPart)
                    {
                        WTPart tempPart = (WTPart) aSubNodePair[1];
                        getSystemReviewObjects(tempPart, pbo, recurse, objectCache);
                    }
                    else if (aSubNodePair[1] instanceof WTPartMaster)
                    {
                        WTPartMaster wtpartmaster = (WTPartMaster) aSubNodePair[1];
                        if (VERBOSE)
                        {
                            System.out.println("	零部件 " + wtpartmaster.getIdentity() + " 没有合适的版本不进行处理");
                        }
                    }
                }
            }
        }
        if (VERBOSE)
            System.out.println("<<<" + CLASSNAME + ".getSystemReviewObjects()---遍历结束 " + thePart.getDisplayIdentity());
    }

    /**
     * 针对某个零部件获取流程随签子件（第一层）列表;该方法由用户“收集随签零部件”请求调用
     *
     * @param thePart
     *            当前零部件
     * @param objectCache
     *            随签对象缓存表：key= oid of object master; value= the object
     */
    public static void getReviewParts(WTPart thePart, WTPart pbo, Hashtable objectCache) throws WTException
    {
        if (VERBOSE)
        {
            System.out.println(">>>" + CLASSNAME + ".getReviewParts()---遍历 " + thePart.getDisplayIdentity());
        }
        boolean recurse = false;
        boolean includeDoc = false;
        // 根据视图找子件
        QueryResult subNodes = WTPartHelper.service.getUsesWTParts(thePart, WTPartStandardConfigSpec.newWTPartStandardConfigSpec(ViewHelper.service.getView(thePart.getViewName()), null));
        while (subNodes.hasMoreElements())
        {
            Persistable aSubNodePair[] = (Persistable[]) subNodes.nextElement();
            if (aSubNodePair[1] instanceof WTPart)
            {
                WTPart tempPart = (WTPart) aSubNodePair[1];
                getReviewObjects(tempPart, pbo, recurse, includeDoc, objectCache);
            }
            else if (aSubNodePair[1] instanceof WTPartMaster)
            {
                WTPartMaster wtpartmaster = (WTPartMaster) aSubNodePair[1];
                if (VERBOSE)
                {
                    System.out.println("	零部件 " + wtpartmaster.getIdentity() + " 没有合适的版本不进行处理");
                }
            }
        }
        if (VERBOSE)
            System.out.println("<<<" + CLASSNAME + ".getReviewParts()---遍历结束 " + thePart.getDisplayIdentity());
    }

    /**
     * 根据当前零部件获取其相关的且可以进行随签的文档和CAD文档
     *
     * @param thePart
     *            当前零部件
     * @param pbo
     *            流程主对象
     * @param objectCache
     *            随签对象缓存表：key= oid of object master; value= the object
     */
    public static void getReviewDocuments(WTPart thePart, WTPart pbo, Hashtable objectCache) throws WTException
    {
        WTPrincipal pboCreator = pbo.getModifier().getPrincipal();
        WTObject objdoc;
        QueryResult qr = PartDocServiceCommand.getAssociatedDescribeDocuments(thePart);
        if (VERBOSE)
        {
            System.out.println(">>>" + CLASSNAME + ".getReviewDocuments()---" + thePart.getDisplayIdentity() + " 找到" + qr.size() + "个描述文档.");
        }
        while (qr.hasMoreElements())
        {
            addReviewDoc((WTObject) qr.nextElement(), pboCreator, objectCache);
        }
    }

    /**
     * 根据当前零部件获取其相关的且可以进行随签的CAD文档
     *
     * @param thePart
     *            当前零部件
     * @param pbo
     *            流程主对象
     * @param objectCache
     *            随签对象缓存表：key= oid of object master; value= the object
     */
    public static void getReviewCADDocuments(WTPart thePart, WTPart pbo, Hashtable objectCache) throws WTException
    {
        WTPrincipal pboCreator = pbo.getModifier().getPrincipal();
        WTObject objdoc;
        QueryResult qr = PartDocServiceCommand.getAssociatedCADDocuments(thePart);
        if (VERBOSE)
        {
            System.out.println(">>>" + CLASSNAME + ".getReviewCADDocuments()---" + thePart.getDisplayIdentity() + " 找到" + qr.size() + "个CAD文档.");
        }
        while (qr.hasMoreElements())
        {
            addReviewDoc((WTObject) qr.nextElement(), pboCreator, objectCache);
        }
    }

    /**
     * 根据业务规则,判断当前的文档或CAD文档是否可以做为随签对象
     *
     * @param doc 当前文档或CAD文档
     * @param pboCreator 流程主对象（为零部件）的创建者，这作为后续随签对象判断所需
     * @param objectCache 随签对象缓存表：key= oid of object master; value= the object
     */
    public static void addReviewDoc(WTObject doc, WTPrincipal pboCreator, Hashtable objectCache)
    {
        if (VERBOSE)
            System.out.println(">>>" + CLASSNAME + ".addReviewDoc()----document=" + doc.getDisplayIdentity());
        try
        {
            if (doc instanceof WTDocument)
            {
                WTDocument theDocument = (WTDocument) doc;
                if (objectCache.get(theDocument.getMaster().toString()) != null)
                    return;
                WTContainer container = theDocument.getContainer();
                String currentDocumentState = theDocument.getState().toString();
                WTPrincipal docCreator = theDocument.getModifier().getPrincipal();
                String bigType = wt.type.ClientTypedUtility.getLocalizedTypeName(theDocument, Locale.CHINA);
                //IBAUtil ibaUtil = new IBAUtil((IBAHolder) theDocument);
                Hashtable ibaValues = IBAUtil.getIBAValues(theDocument);

                String docType = WfAugmentUtil.getPropertiesValue("ext.generic.wfaugment.wfaugment", "wf.doc.smallType");
                String detailType = (String) ibaValues.get(docType);
                String fullType ="";
                if (VERBOSE)
                    System.out.println("\t 文档大类为 " + bigType + "，文档小类软属性为 " + docType + "，其值为 " + detailType);
                if (detailType == null)
                	detailType="";
                	
                    
                if (VERBOSE)
                    System.out.println("    最终小类为:" + detailType);
                String processInfo = (String) ibaValues.get("ProcessInfo");
                fullType=bigType + "." + detailType;                 
                if (VERBOSE)
                    System.out.println("	full type=" + fullType);
                // check the ProcessInfo
                if (processInfo == null || processInfo.length() <= 0 || processInfo.equals(PROCESS_INFO_CLEAR_LABEL))
                {

                }
                else
                {
                    return;
                }

                getReviewDocTypes(container);

                Hashtable reviewDocType = (Hashtable) reviewDocTypes.get(container.toString());
                if (reviewDocType == null)
                    return;
                else
                {
                    String reviewFlag = (String) reviewDocType.get(fullType);
                    if (VERBOSE)
                        System.out.println("  doc reviewFlag=" + reviewFlag);
                    if (reviewFlag == null)
                        return;
                    else if (reviewFlag.equals("Y"))
                    {
                        if (currentDocumentState.equals("INWORK"))
                        {
                            if (pboCreator.getName().equals(docCreator.getName()))
                            {
                                objectCache.put(theDocument.getMaster().toString(), theDocument);
                                if (VERBOSE)
                                    System.out.println("	" + theDocument.getDisplayIdentity() + " 已加入随签列表.");
                            }
                        }
                        else if (currentDocumentState.equals("WAITREVIEW"))
                        {
                            objectCache.put(theDocument.getMaster().toString(), theDocument);
                            if (VERBOSE)
                                System.out.println("	" + theDocument.getDisplayIdentity() + " 已加入随签列表.");
                        }
                    }
                    else
                        return;
                    // 需要考虑小类为"*"的情况

                }
            }
            else if (doc instanceof EPMDocument)
            {
                EPMDocument epmdoc = (EPMDocument) doc;
                if (objectCache.get(epmdoc.getMaster().toString()) != null)
                    return;
                WTPrincipal theEPMDocumentCreator = epmdoc.getModifier().getPrincipal();
                String currentEPMDocumentState = epmdoc.getLifeCycleState().toString();
                if (currentEPMDocumentState.equals("INWORK"))
                {
                    if (pboCreator.getName().equals(theEPMDocumentCreator.getName()))
                    {
                        objectCache.put(epmdoc.getMaster().toString(), epmdoc);
                        if (VERBOSE)
                            System.out.println("	" + epmdoc.getDisplayIdentity() + " 已加入随签列表.");
                    }
                }
                else if (currentEPMDocumentState.equals("WAITREVIEW"))
                {
                    objectCache.put(epmdoc.getMaster().toString(), epmdoc);
                    if (VERBOSE)
                        System.out.println("	" + epmdoc.getDisplayIdentity() + " 已加入随签列表.");
                }
            }
        }
        catch (WTException wte)
        {
            System.out.println(wte);
        }
        catch (IOException ioe)
        {
            System.out.println(ioe);
        }
        if (VERBOSE)
            System.out.println("<<<" + CLASSNAME + ".addReviewDoc()----document=" + doc.getDisplayIdentity());
    }

    /**
     *初始化需要打印签审图的对象列表
     * @param reviewObjects
     * @return
     * @throws WTException
     */
    public static Vector initializePrintDraftObjects(Vector reviewObjects) throws WTException
    {
        if (VERBOSE)
            System.out.println(">>>" + CLASSNAME + ".initializePrintDraftObjects()");
        Vector printDraftObjects = new Vector();
        try
        {
            for (int i = 0; i < reviewObjects.size(); i++)
            {
                Object reviewObject = reviewObjects.elementAt(i);
                if (reviewObject instanceof EPMDocument)
                {
                    String masterOid = ((EPMDocument) reviewObject).getMaster().toString();
                    String template = (String) IBAUtil.getIBAValue((EPMDocument) reviewObject, "TEMPLATE");
                    if (VERBOSE)
                        System.out.println("	" + ((EPMDocument) reviewObject).getDisplayIdentity() + "-----template=" + template);
                    if (template == null || template.length() <= 0)
                        continue;
                    else if (template.indexOf("A0") >= 0 || template.indexOf("A1") >= 0 || template.indexOf("A2") >= 0)
                    {
                        printDraftObjects.add(masterOid);
                        if (VERBOSE)
                            System.out.println("    add " + ((EPMDocument) reviewObject).getDisplayIdentity() + "  into the print draft list.");
                    }
                }
            }
        }
        catch (Exception exception)
        {
            throw new WTException(exception);
        }
        if (VERBOSE)
            System.out.println("<<<" + CLASSNAME + ".initializePrintDraftObjects()---result count=" + printDraftObjects.size());
        return printDraftObjects;
    }

    /**
     *保存用户选择的打印签审草图的信息
     * @param reviewObjects
     * @return
     * @throws WTException
     */
    public static WfActivity savePrintDraftObjects(WfActivity wfactivity, NmCommandBean nmcommandbean) throws WTException
    {
        if (VERBOSE)
            System.out.println(">>>" + CLASSNAME + ".savePrintDraftObjects()");
        Vector printDraftObjects = new Vector();
        try
        {
            HashMap checked = nmcommandbean.getChecked();
            if (VERBOSE)
                System.out.println("	checked map=" + checked);
            if (checked == null || checked.size() <= 0)
            {
                if (VERBOSE)
                    System.out.println("	not select any objects. need clear the object list");
            }
            else
            {
                Iterator keys = checked.keySet().iterator();
                while (keys.hasNext())
                {
                    String key = (String) keys.next();
                    if (VERBOSE)
                        System.out.println("	key=" + key);
                    if (key.indexOf(WfPrintInfoDataUtility.PrintDraftFlagPrifix) >= 0)
                    {
                        String split[] = key.split("_");
                        String masterOid = split[1];
                        printDraftObjects.add(masterOid);
                    }
                }
            }
            if (VERBOSE)
                System.out.println("	new  printDraftObjects=" + printDraftObjects);
            ProcessData context = wfactivity.getContext();
            Object value = context.getValue("printDraftObjects");
            if (VERBOSE)
                System.out.println("	source value=" + value);
            if (value != null) //说明该流程中存在该变量，此种情况下才更新变量.
            {
                context.setValue("printDraftObjects", printDraftObjects);
                wfactivity.setContext(context);
                wfactivity = (WfActivity) wt.fc.PersistenceHelper.manager.save(wfactivity);
                if (VERBOSE)
                    System.out.println("    printDraftObjects updated.");
            }
        }
        catch (Exception exception)
        {
            throw new WTException(exception);
        }
        if (VERBOSE)
            System.out.println("<<<" + CLASSNAME + ".savePrintDraftObjects()---result count=" + printDraftObjects.size());
        return wfactivity;
    }


    /**
     * 从流程中获取需要打印的对象
     */
    public static Vector getPrintObjects(WorkItem wi) throws WTException
    {
        WfAssignedActivity wfassignedactivity = (WfAssignedActivity) wi.getSource().getObject();
        Vector objects = new Vector();
        objects = (Vector) (wfassignedactivity.getContext().getValue("printObjects"));
        return objects;
    }

    /**
     * 从流程中获取需要打印签审草图的对象
     */
    public static Vector getPrintDraftObjects(WorkItem wi) throws WTException
    {
        WfAssignedActivity wfassignedactivity = (WfAssignedActivity) wi.getSource().getObject();
        Vector result = new Vector();
        Vector printDraftObjects = new Vector();
        printDraftObjects = (Vector) (wfassignedactivity.getContext().getValue("printDraftObjects"));
        if (printDraftObjects == null || printDraftObjects.size() <= 0)
        {
            if (VERBOSE)
                System.out.println("	print draft objects is null or empty. return;");
            return result;
        }
        Vector printObjects = new Vector();
        printObjects = (Vector) (wfassignedactivity.getContext().getValue("printObjects"));
        if (printObjects == null)
        {
            printObjects = (Vector) (wfassignedactivity.getContext().getValue("reviewObjs"));
            if (VERBOSE)
                System.out.println("    print objects is null or empty. so get print draft objects from reviewObjs.");
        }
        if (VERBOSE)
            System.out.println("	print objects=" + printObjects);
        if (printObjects != null && printObjects.size() > 0)
        {
            for (int i = 0; i < printObjects.size(); i++)
            {
                Object printObject = printObjects.elementAt(i);
                if (printObject instanceof EPMDocument)
                {
                    if (printDraftObjects.contains(((EPMDocument) printObject).getMaster().toString()))
                        result.add(printObject);
                }
            }
        }
        else
        {
            if (VERBOSE)
                System.out.println("    print objects is null or empty. so get print draft objects from reviewObjs.");
        }
        if (VERBOSE)
            System.out.println("	print draft objects count=" + result.size());
        return result;
    }

    /**
     * 获取CAD文档的直接相关参考文档（即绘图将三维模型作为绘图模型）
     * @param built 当前CAD文档
     * @throws WTException
     */
    public static QueryResult getDirectReferencedByEPMDocuments(EPMDocument built) throws WTException
    {
        if (VERBOSE)
            System.out.println(">>>" + CLASSNAME + ".getDirectReferencedByEPMDocuments()---built=" + built.getDisplayIdentity());

        // 获取CAD文档的参考文档，指挂在该CAD文档下的文档
        QuerySpec qs = new QuerySpec(EPMReferenceLink.class);
        SearchCondition sc = new SearchCondition(EPMReferenceLink.class, EPMReferenceLink.DEP_TYPE, SearchCondition.EQUAL, 4);
        qs.appendSearchCondition(sc);
        QueryResult qr = EPMStructureHelper.service.navigateReferencedBy((EPMDocumentMaster) built.getMaster(), qs, true);

        if (VERBOSE)
        {
            System.out.println("	cad documents count=" + qr.size());
            System.out.println("<<<" + CLASSNAME + ".getDirectReferencedByEPMDocuments()---built=" + built.getDisplayIdentity());
        }
        return qr;
    }

    /**
     * 【流程直接调用】检查随签对象，并将出现不符合条件的对象记录下来，并最终抛出错误
     *
     * @param reviewObjects
     *            零部件流程的随签对象列表
     * @throws WTException
     */
    public static WTArrayList checkReviewObjectsForSubmit(WTArrayList reviewObjects) throws WTException
    {
        if (VERBOSE)
        {
            System.out.println(">>>" + CLASSNAME + ".checkReviewObjectsForSubmit()");
        }
        StringWriter errBuf = new StringWriter();
        PrintWriter pw = new PrintWriter(errBuf);

        for (int i = 0; i < reviewObjects.size(); i++)
        {
            WTObject wtobject = (WTObject) reviewObjects.getPersistable(i);
            wtobject = (WTObject) PersistenceHelper.manager.refresh(wtobject);
            // 对于不是最新小版本的对象，获取其最新小版本，然后检查其是否检出；如果是检出，则记录在错误信息缓存中；
            if (!((Iterated) wtobject).isLatestIteration())
            {
                WTObject iterated = (WTObject) VersionControlHelper.service.getLatestIteration((Iterated) wtobject, false);
                if (ext.com.workflow.WorkflowUtil.isObjectCheckedOut(iterated))
                {
                    pw.println(iterated.getDisplayIdentity() + " 被检出.");
                }
                else
                {
                    reviewObjects.remove(wtobject);
                    reviewObjects.add(iterated);
                }
            }
            // 对于是最新小版本的对象，检查其是否检出；如果是检出，则记录在错误信息缓存中；
            else
            {
                if (ext.com.workflow.WorkflowUtil.isObjectCheckedOut(wtobject))
                {
                    pw.println(wtobject.getDisplayIdentity() + " 被检出.");
                }
            }
        }

        pw.flush();
        if (errBuf.toString().length() > 0)
        {
            throw new WTException(errBuf.toString());
        }

        if (VERBOSE)
        {
            System.out.println("<<<" + CLASSNAME + ".checkReviewObjectsForSubmit()");
        }
        return reviewObjects;
    }

    /**
     * 在“提交”前检查随签零部件以及非随签零部件：如果非随签零部件状态不是“已发布”，则记录到列表中，并以错误信息抛出；如果随签零部件不是检入状态，则记录到列表中，并以错误信息抛出
     *
     * @param pbo 当前零部件流程的主对象
     * @param reviewObjects 零部件流程的随签对象列表
     * @return 不符合条件的零部件列表
     * @throws WTException
     */
    public static WTArrayList checkReviewObjectsForSubmit2(WTObject pbo, WTArrayList reviewObjects) throws WTException
    {
        if (VERBOSE)
            System.out.println(">>>" + CLASSNAME + ".checkReviewObjectsForSubmit2()");
        StringWriter errBuf = new StringWriter();
        PrintWriter pw = new PrintWriter(errBuf);
        Hashtable errParts = new Hashtable();
        Hashtable checkedObjects = new Hashtable();
        for (int i = 0; i < reviewObjects.size(); i++)
        {
        	 WTObject wtobject = (WTObject) reviewObjects.getPersistable(i);           
             wtobject = (WTObject) PersistenceHelper.manager.refresh(wtobject);
             if (!(wtobject instanceof WTPart))
             {
                 continue;
             }else{
             	WTPart part=(WTPart)wtobject;
             	 System.out.println("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee:="+part.getName()+part.getNumber());
             }
        }
        
       
        for (int i = 0; i < reviewObjects.size(); i++)
        {
            WTObject wtobject = (WTObject) reviewObjects.getPersistable(i);           
            wtobject = (WTObject) PersistenceHelper.manager.refresh(wtobject);
            System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>wtobject="+wtobject);
            if (checkedObjects.get(wtobject.toString()) != null)
                continue;
            else
            {
                checkedObjects.put(wtobject.toString(), wtobject);
            }

            // 对于不是最新小版本的对象，获取其最新小版本，然后检查其是否检出；如果是检出，则记录在错误信息缓存中；
            if (!((Iterated) wtobject).isLatestIteration())
            {
                WTObject iterated = (WTObject) VersionControlHelper.service.getLatestIteration((Iterated) wtobject, false);
                if (ext.com.workflow.WorkflowUtil.isObjectCheckedOut(iterated))
                {
                    pw.println("随签的对象 " + iterated.getDisplayIdentity() + " 被检出.");
                }
                else
                {
                    reviewObjects.remove(wtobject);
                    reviewObjects.add(iterated);
                }
            }
            // 对于是最新小版本的对象，检查其是否检出；如果是检出，则记录在错误信息缓存中；
            else
            {
                if (ext.com.workflow.WorkflowUtil.isObjectCheckedOut(wtobject))
                {
                    pw.println("随签的对象 " + wtobject.getDisplayIdentity() + " 被检出.");
                }
            }


            if (!(wtobject instanceof WTPart))
            {
                continue;
            }else{
            	WTPart part=(WTPart)wtobject;
            	 System.out.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxw:="+part.getName()+part.getNumber());
            }

            WTPart thePart = (WTPart) wtobject;
            // 根据视图找子件
            QueryResult subNodes = WTPartHelper.service.getUsesWTParts(thePart, WTPartStandardConfigSpec.newWTPartStandardConfigSpec(ViewHelper.service.getView(thePart.getViewName()), null));
            System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>size="+subNodes.size());
            while (subNodes.hasMoreElements())
            {
                Persistable aSubNodePair[] = (Persistable[]) subNodes.nextElement();
               // System.out.println("*************************************aSubNodePair="+aSubNodePair[0]);
                if (aSubNodePair[1] instanceof WTPart)
                {
                    WTPart tempPart = (WTPart) aSubNodePair[1];
                    System.out.println("*************************************tempPart="+tempPart.getName());
                    if (reviewObjects.contains(tempPart))
                    {
                        continue;
                    }
                    else
                    {
                        if (errParts.get(tempPart.toString()) == null)
                        {
                            String state = tempPart.getLifeCycleState().toString();
                            if (!state.equals("RELEASED"))
                            {
                                pw.println("非随签的零部件 " + tempPart.getDisplayIdentity() + " 还没有发布.");
                                errParts.put(tempPart.toString(), tempPart);
                                throw new WTException("非随签的零部件 " + tempPart.getDisplayIdentity() + " 还没有发布.");
                            }
                        }
                    }
                }
                else if (aSubNodePair[1] instanceof WTPartMaster)
                {
                    WTPartMaster wtpartmaster = (WTPartMaster) aSubNodePair[1];
                    if (VERBOSE)
                    {
                        System.out.println("    零部件 " + wtpartmaster.getIdentity() + " 没有合适的版本不进行处理");
                    }
                }
            }
        }

//        pw.flush();
//        if (errBuf.toString().length() > 0)
//        {                
//            throw new WTException(errBuf.toString());
//        }

        if (VERBOSE)
        {
            System.out.println("<<<" + CLASSNAME + ".checkReviewObjectsForSubmit2()");
        }
        return reviewObjects;
    }

    /**
     * 在“批准”前检查非随签零部件，如果这些零部件状态不是“已发布”，则记录到列表中，并以错误信息抛出；
     *
     * @param pbo 当前零部件流程的主对象
     * @param reviewObjects 零部件流程的随签对象列表
     * @return 不符合条件的非随签零部件列表
     * @throws WTException
     */
    public static Vector checkObjectsForApprove(WTObject pbo, WTArrayList reviewObjects) throws WTException
    {
        if (VERBOSE)
            System.out.println(">>>" + CLASSNAME + ".checkObjectsForApprove()");
        StringWriter errBuf = new StringWriter();
        PrintWriter pw = new PrintWriter(errBuf);
        Hashtable errParts = new Hashtable();
        Hashtable checkedObjects = new Hashtable();

        for (int i = 0; i < reviewObjects.size(); i++)
        {
            WTObject wtobject = (WTObject) reviewObjects.getPersistable(i);
            if (checkedObjects.get(wtobject.toString()) != null)
                continue;
            else
            {
                checkedObjects.put(wtobject.toString(), wtobject);
                if (!(wtobject instanceof WTPart))
                {
                    continue;
                }
            }

            WTPart thePart = (WTPart) wtobject;
            // 根据视图找子件
            QueryResult subNodes = WTPartHelper.service.getUsesWTParts(thePart, WTPartStandardConfigSpec.newWTPartStandardConfigSpec(ViewHelper.service.getView(thePart.getViewName()), null));
            while (subNodes.hasMoreElements())
            {
                Persistable aSubNodePair[] = (Persistable[]) subNodes.nextElement();
                if (aSubNodePair[1] instanceof WTPart)
                {
                    WTPart tempPart = (WTPart) aSubNodePair[1];
                    if (reviewObjects.contains(tempPart))
                    {
                        continue;
                    }
                    else
                    {
                        if (errParts.get(tempPart.toString()) == null)
                        {
                            String state = tempPart.getLifeCycleState().toString();
                            if (!state.equals("RELEASED"))
                            {
                                pw.println(tempPart.getDisplayIdentity() + " 还没有发布.");
                                errParts.put(tempPart.toString(), tempPart);
                            }
                        }
                    }
                }
                else if (aSubNodePair[1] instanceof WTPartMaster)
                {
                    WTPartMaster wtpartmaster = (WTPartMaster) aSubNodePair[1];
                    if (VERBOSE)
                    {
                        System.out.println("	零部件 " + wtpartmaster.getIdentity() + " 没有合适的版本不进行处理");
                    }
                }
            }
        }

        pw.flush();
        if (errBuf.toString().length() > 0)
        {
            throw new WTException(errBuf.toString());
        }

        if (VERBOSE)
        {
            System.out.println("<<<" + CLASSNAME + ".checkObjectsForApprove()");
        }
        return new Vector(errParts.values());
    }

    /**
     * 修改随签对象状态,并在随签对象的"随签流程"属性中记录流程信息，以避免对象跟随其它流程签审
     * @param reviewObjects 随签对象列表
     * @param toState 目标状态
     * @param isSetProcessInfo 是否设置“随签流程”属性
     */
    public static WTArrayList modifyStateAndProcessInfo(ObjectReference self, WTArrayList reviewObjects, String toState, boolean isSetProcessInfo) throws WTException, java.rmi.RemoteException
    {
        if (VERBOSE)
            System.out.println(">>>" + CLASSNAME + ".modifyStateAndProcessInfo()");
        WfProcess wfprocess = ext.com.workflow.WorkflowUtil.getProcess(self);
        ReferenceFactory rf = new ReferenceFactory();
        String processInfo = rf.getReferenceString(wfprocess);
        for (int j = 0; j < reviewObjects.size(); j++)
        {
            LifeCycleManaged lcm = (LifeCycleManaged) reviewObjects.getPersistable(j);
            if (WorkInProgressHelper.isCheckedOut((Workable) lcm))
            {
                throw new WTException(" 对象 " + ((WTObject) lcm).getDisplayIdentity() + " 被检出，无法修改状态!");
            }
            lcm = (LifeCycleManaged) ext.com.workflow.WorkflowUtil.setLifeCycleState(lcm, toState);
            if (VERBOSE)
                System.out.println("	" + ((WTObject) lcm).getDisplayIdentity() + " lifecycle state is set to " + toState);
            if (isSetProcessInfo)
            {
                Hashtable updateIBAValues = new Hashtable();
                updateIBAValues.put("ProcessInfo", processInfo);
                lcm = (LifeCycleManaged)IBAUtil.forceSetIBAValues((wt.iba.value.IBAHolder) lcm, updateIBAValues);
                if (VERBOSE)
                    System.out.println("	" + ((WTObject) lcm).getDisplayIdentity() + " ProcessInfo is set");
            }
            reviewObjects.set(j, lcm);
        }
        if (VERBOSE)
            System.out.println("<<<" + CLASSNAME + ".modifyStateAndProcessInfo()");
        return reviewObjects;
    }

    /**
     * 获得针对对象的某个action的URL
     */
    public static String getObjectURL(WTObject object, String type, String action) throws WTException
    {
        // WfProcess wfprocess = WorkflowUtil.getProcess(self);
        ReferenceFactory rf = new ReferenceFactory();
        String oid = rf.getReferenceString(object);

        URLFactory urlfactory = new URLFactory();
        HashMap hashmap = new HashMap();
        hashmap.put("oid", oid);

        String s1 = NmActionServiceHelper.service.getAction(type, action).getUrl();
        String url = urlfactory.getHREF(s1, hashmap, true);

        String urlLink = object.getDisplayIdentity() + "---" + url;
        if (VERBOSE)
            System.out.println("urlLink = " + urlLink);
        return urlLink;
    }

    /**
     * 获得针对对象的某个action的Href
     */
    public static String getObjectURLLink(WTObject object, String type, String action) throws WTException
    {
        // WfProcess wfprocess = WorkflowUtil.getProcess(self);
        ReferenceFactory rf = new ReferenceFactory();
        String oid = rf.getReferenceString(object);

        URLFactory urlfactory = new URLFactory();
        HashMap hashmap = new HashMap();
        hashmap.put("oid", oid);

        String s1 = NmActionServiceHelper.service.getAction(type, action).getUrl();
        String url = urlfactory.getHREF(s1, hashmap, true);

        String urlLink = "<a href=\"" + url.toString() + "\" target=\"_blank\" >" + object.getDisplayIdentity() + "</a>";
        if (VERBOSE)
            System.out.println("urlLink = " + urlLink);
        return urlLink;
    }

    /**
     * 当复制或修订产生的新对象，清除一些不需要的iba属性
     *
     * @param obj 新生成的对象
     *
     * @param mode 对象生成模式：revise,copy
     */

    public static WTObject clearHistoricalIBA(WTObject obj, String mode) throws WTException
    {
        if (VERBOSE)
            System.out.println(">>>" + CLASSNAME + ".clearHistoricalIBA()");
        if (!(obj instanceof IBAHolder))
            return obj;
        // 属性名，代表应该清除的iba，例如：
        // wt.part.WTPart.copy.clearIBA=VERSION_INFO,CREATOR
        // wt.part.WTPart.revise.clearIBA=VERSION_INFO,CREATOR
        // wt.doc.WTDocument.copy.clearIBA=VERSION_INFO,CREATOR
        // wt.doc.WTDocument.revise.clearIBA=VERSION_INFO,CREATOR
        String propertyName = obj.getClass().getName() + "." + mode + ".clearIBA";
        String property = getValueFromProperties(propertyName, PROPERTIES);
        if (VERBOSE)
            System.out.println("	" + propertyName + "=" + property);
        if (property == null || property.length() <= 0)
            return obj;
        String clearIBAs[] = property.split(",");
        if (VERBOSE)
        {
            for (int i = 0; i < clearIBAs.length; i++)
            {
                System.out.println("	clearIBAs[ " + i + "]=" + clearIBAs[i]);
            }
        }
        try
        {
            Hashtable ibaValues = ext.com.iba.IBAUtil.getIBAValues((wt.iba.value.IBAHolder) obj);
            Hashtable updateIBAValues = new Hashtable();

            for (int j = 0; j < clearIBAs.length; j++)
            {
                String value = (String) ibaValues.get(clearIBAs[j]);
                if (value == null || value.length() <= 0 || value.equals(PROCESS_INFO_CLEAR_LABEL))
                {
                    continue;
                }
                updateIBAValues.put(clearIBAs[j], PROCESS_INFO_CLEAR_LABEL);
            }
            if (updateIBAValues.size() > 0)
            {
                ext.com.iba.IBAUtil.forceSetIBAValues((wt.iba.value.IBAHolder) obj, updateIBAValues);
                if (VERBOSE)
                    System.out.println("    cleared iba values=" + updateIBAValues);
            }
        }
        catch(Exception exception)
        {
            throw new WTException(exception);
        }
     
        if (VERBOSE)
            System.out.println("<<<" + CLASSNAME + ".clearHistoricalIBA()");
        return obj;
    }

    /**
     * 从特定的properties文件中获取某个属性值
     * @param key 属性名
     * @param propertiesFile 属性文件路径标识，例如：ext.generic.part.generic_part
     */
    public static String getValueFromProperties(String key, String propertiesFile) throws WTException
    {
        String strinfo = "";
        try
        {
            PropertyResourceBundle prBundle = (PropertyResourceBundle) PropertyResourceBundle.getBundle(propertiesFile);
            byte temp[] = null;
            temp = key.getBytes("GB2312");
            key = new String(temp, "ISO-8859-1");
            temp = prBundle.getString(key).getBytes("ISO-8859-1");
            strinfo = new String(temp, "GB2312");
        }
        catch (MissingResourceException mre)
        {
            mre.printStackTrace();
        }
        catch (UnsupportedEncodingException uee)
        {
            uee.printStackTrace();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        return strinfo;
    }
    
    /*
     * 
     */
	public static void setSQEParticipants(Object obj,String role,String[] participant,WTPart part){
		
		if(obj == null || role == null || part == null){
			return ;
		}
		try {
			String specialMonitor = (String) IBAUtil.getIBAValue(part, "specialMonitor");
			String partName = part.getName();
			String contact = partName + "." + specialMonitor;
			System.out.println("setSQEParticipants method contact = " + contact);
			String userName = PartWorkflowUtil.getValueFromProperties(contact, filePath);
			System.out.println("setSQEParticipants method userName = " + userName);
			Vector userList = PartCommands.getUserList(userName);
			System.out.println("setSQEParticipants method userList = " + userList.toString());
			for (Object user : userList) {
				if(user instanceof WTUser){
					user = (WTUser)user;
					WorkflowUtil.addPrincipalToProcessRole(obj, role, (WTPrincipal)user);
				}
			}
		} catch (RemoteException e) {
			e.printStackTrace();
		} catch (WTException e) {
			e.printStackTrace();
		}
	}
  
     	
    public static void main(String[] args) throws WTException
    {
    	WTArrayList arry= getReviewObjs("OR:wt.workflow.work.WorkItem:217216");
    	for(int i=0;i<arry.size();i++){
        		ObjectReference obj=(ObjectReference)arry.get(i);
            	Persistable per=(Persistable)obj.getObject();
            	System.out.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx="+per.getIdentity()+"****"+per);
        	 }
    }
}
